package com.example.mybatisplus.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.mybatisplus.mapper.*;
import com.example.mybatisplus.model.domain.*;
import com.example.mybatisplus.mapper.RoomMapper;
import com.example.mybatisplus.model.domain.AdjustDormitory;
import com.example.mybatisplus.model.domain.Dot;
import com.example.mybatisplus.model.domain.Student;
import com.example.mybatisplus.mapper.StudentMapper;
import com.example.mybatisplus.model.dto.RepairForm;
import com.example.mybatisplus.model.dto.StudentForm;
import com.example.mybatisplus.model.dto.StudentStudyForm;
import com.example.mybatisplus.service.AdjustDormitoryService;
import com.example.mybatisplus.service.StudentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static com.baomidou.mybatisplus.core.toolkit.StringUtils.capitalize;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zzy
 * @since 2024-06-24
 */
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {
    @Autowired
    private StudentMapper studentMapper;
    @Autowired
    private RoomMapper roomMapper;
    @Autowired
    private AdjustDormitoryService adjustDormitoryService;
    @Autowired
    private BuildingMapper buildingMapper;
    @Autowired
    private DormitoryAdminMapper dormitoryAdminMapper;
    @Autowired
    private RepairMapper repairMapper;

    public List<Student> selectPage(Dot dot) {
        Page<Student> studentPage = new Page<>(dot.getPageNo(), dot.getPageSize());
        IPage<Student> studentIPage = this.getBaseMapper().selectPage(studentPage, null);
        return studentIPage.getRecords();
    }


    public List<StudentForm> selectPageByNameAndAccount(Dot dot) {
        List<StudentForm> students = this.getBaseMapper().selectByNameAndAccount(dot);
        return students;
    }


    public List<Student> listByAccounts(List<String> accountList) {
        List<Student> students = this.getBaseMapper().listByAccounts(accountList);
        return students;
    }

    @Override
    public List<Student> selectStudentByCollegeIdAndMajorIdAndClassId(Dot dot) {
        List<Student> list = studentMapper.selectStudentByCollegeIdAndMajorIdAndClassId(dot);
        return list;
    }

    @Override
    public List<Student> handSelectStudentByBuilding(Long areaID, Long buildingID, Long roomID) {
        List<Student> list = studentMapper.handSelectStudentByBuilding(areaID, buildingID, roomID);
        return list;
    }

    @Override
    public List<Student> selectStudentByCollegeName(Dot dot) {
        return studentMapper.selectStudentByCollegeName(dot);
    }

    @Override
    public List<Student> selectStudentByNames(Dot dot) {
        return studentMapper.selectStudentByNames(dot);
    }

    @Override
    public StudentStudyForm selectMajorNameAndCollegeNameByStudentID(Long studentID) {
        return studentMapper.selectMajorNameAndCollegeNameByStudentID(studentID);
    }
    public static <K, V> Map<K, V> convertObjectToMap(Object object) {
        if (object instanceof Map<?, ?>) {
            // 如果Object是Map类型，直接转换
            return (Map<K, V>) object;
        } else {
            // 如果Object不是Map类型，抛出异常或者进行其他处理
            throw new IllegalArgumentException("The Object is not a Map");
        }
    }


    public List<Student> convertObjectToListStudent(Object object) throws Exception {
        // 首先检查object是否是List类型
        if (object instanceof List) {
            List<?> listObj = (List<?>) object;

            // 创建一个空的List<Student>
            List<Student> listStudent = new ArrayList<>();

            // 遍历列表
            for (Object item : listObj) {
                // 检查列表中的每个元素是否是Map类型
                if (item instanceof Map) {
                    Map<String, Object> map = (Map<String, Object>) item;
                    // 使用之前提供的转换方法
                    listStudent.add(convertMapToStudent(map));
                } else {
                    // 如果不是Map类型，抛出异常或进行其他处理
                    throw new Exception("List contains non-Map elements");
                }
            }

            return listStudent;
        } else {
            // 如果object不是List类型，抛出异常
            throw new Exception("Provided object is not a List");
        }
    }

    private static Student convertMapToStudent(Map<String, Object> map) {
        // 这里使用前面提供的转换逻辑
        Student student = new Student();

        // 遍历Map中的键值对
        for (Map.Entry<String, Object> entry : map.entrySet()) {

            String fieldName = entry.getKey();
            Object fieldValue = entry.getValue();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
            switch (fieldName){
                case "id":
                    student.setId(Long.parseLong(fieldValue.toString()));
                    break;
                case "modifiedTime":
                    student.setModifiedTime(LocalDateTime.parse((String)fieldValue, formatter));
                    break;
                case "createdTime":
                    student.setCreatedTime(LocalDateTime.parse((String)fieldValue, formatter));
                    break;
                case "gender":
                    student.setGender((String) fieldValue);
                    break;
                case "name":
                    student.setName((String) fieldValue);
                    break;
                case "password":
                    student.setPassword((String) fieldValue);
                    break;
                case "nation":
                    student.setNation((String) fieldValue);
                    break;
                case "birthplace":
                    student.setBirthplace((String) fieldValue);
                    break;
                case "classId":
                    student.setClassId(Long.parseLong(fieldValue.toString()));
                    break;
                case "major":
                    student.setMajor(Long.parseLong(fieldValue.toString()));
                    break;
                case "account":
                    student.setAccount((String) fieldValue);
                    break;
                case "isDeleted":
                    student.setIsDeleted((Integer) fieldValue);
                    break;
                case "room":

                    student.setRoom(fieldValue==null ?null:Long.parseLong(fieldValue.toString()));
                    break;

            }
//
//            try {
//                // 构造setter方法名
//                String methodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
//
//                // 获取Student类中对应的方法
//                Method method = Student.class.getMethod(methodName, fieldValue.getClass());
//
//                // 调用setter方法设置属性值
//                method.invoke(student, fieldValue);
//            } catch (Exception e) {
//                // 异常处理，例如打印堆栈信息或记录日志
//                e.printStackTrace();
//            }
        }

        return student;
    }

    @Override
    @Transactional
    public String batchAllocationWithBirthplace(Map<String, Object> names) {
        List<Map<String, Object>> mapList = roomMapper.selectBuildingLivingCond(names);
        Long leaderID = Long.parseLong(names.get("LeaderID").toString());
        Long buildingID = Long.parseLong(names.get("BuildingID").toString());
        List<Student> list = null;
        try {
            list = convertObjectToListStudent(names.get("students"));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        List<Long> idList = new ArrayList<>();
        list.forEach(s->{idList.add(s.getId());});
        if(!idList.isEmpty())list = studentMapper.selectBatchIds(idList);
        Collections.sort(list,
                Comparator.comparing(Student::getBirthplace)
        );

        int studentIter = 0;
        List<AdjustDormitory> adjustDormitories = new ArrayList<>();
        for(Map<String, Object> map:mapList){
            Long ID = (Long)map.get("roomID");
            Long count = (Long)map.get("count");
            // 如果存在少于六人，则根据寝室内部的人数开始分配寝室

            if(count<6){

                for(;count<6;count++){
                    if(studentIter<list.size()) {
                        if(list.get(studentIter).getRoom()!=null){
                            return String.format("Student %s has already had a room.", list.get(studentIter).getName());
                        }
                        Student student = list.get(studentIter);
                        adjustDormitories.add(
                                new AdjustDormitory()
                                        .setState("已完成")
                                        .setStudent(student.getId())
                                        .setInRoom(ID)
                                        .setLeader(leaderID)
                                        .setCreatedTime(LocalDateTime.now())
                                        .setModifiedTime(LocalDateTime.now())
                                        .setInBuilding(buildingID)

                        );
                        list.get(studentIter++)
                                .setRoom(ID)
                                .setModifiedTime(LocalDateTime.now());
                    }
                }
            }
        }

        if(studentIter>list.size())return "Allocate success in this building, but the building is full. You need to reassign some students' rooms.";
        if(list!=null && !list.isEmpty()){
            this.updateBatchById(list);
            adjustDormitoryService.saveBatch(adjustDormitories);
        }
        return "Allocate success";
    }

    @Override
    @Transactional
    public String batchAllocationWithNation(Map<String, Object> names) {
        List<Map<String, Object>> mapList = roomMapper.selectBuildingLivingCond(names);
        Long leaderID = Long.parseLong(names.get("LeaderID").toString());
        Long buildingID = Long.parseLong(names.get("BuildingID").toString());
        List<Student> list = null;
        try {
            list = convertObjectToListStudent(names.get("students"));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        List<Long> idList = new ArrayList<>();
        list.forEach(s->{idList.add(s.getId());});
        if(!idList.isEmpty())list = studentMapper.selectBatchIds(idList);
        Collections.sort(list,
                Comparator.comparing(Student::getNation));

        int studentIter = 0;
        List<AdjustDormitory> adjustDormitories = new ArrayList<>();
        for(Map<String, Object> map:mapList){
            Long ID = (Long)map.get("roomID");
            Long count = (Long)map.get("count");
            // 如果存在少于六人，则根据寝室内部的人数开始分配寝室

            if(count<6){

                for(;count<6;count++){
                    if(studentIter<list.size()) {
                        if(list.get(studentIter).getRoom()!=null){
                            return String.format("Student has already had a room.");
                        }
                        Student student = list.get(studentIter);
                        adjustDormitories.add(
                                new AdjustDormitory()
                                        .setState("已完成")
                                        .setStudent(student.getId())
                                        .setInRoom(ID)
                                        .setLeader(leaderID)
                                        .setCreatedTime(LocalDateTime.now())
                                        .setModifiedTime(LocalDateTime.now())
                                        .setInBuilding(buildingID)
                        );
                        list.get(studentIter++)
                                .setRoom(ID)
                                .setModifiedTime(LocalDateTime.now());
                    }
                }
            }
        }

        if(studentIter>list.size())return "Allocate success in this building, but the building is full. You need to reassign some students' rooms.";
        if(list!=null && !list.isEmpty()){
            this.updateBatchById(list);
            adjustDormitoryService.saveBatch(adjustDormitories);
        }
        return "Allocate success";
    }

    @Override
    public List<Student> selectStudentByAll(Dot dot) {
        return studentMapper.selectStudentByAll(dot);

    }

    @Override
    @Transactional
    public String batchExchange(Map<String, Object> names) {
        List<Map<String, Object>> mapList = roomMapper.selectBuildingLivingCond(names);
        Long leaderID = Long.parseLong(names.get("LeaderID").toString());
        Long buildingID = Long.parseLong(names.get("BuildingID").toString());
        List<Student> list = null;
        try {
            list = convertObjectToListStudent(names.get("students"));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
//        Collections.sort(list,
//                Comparator.comparing(Student::getNation));
        int studentIter = 0;
        List<AdjustDormitory> adjustDormitories = new ArrayList<>();
        for(Map<String, Object> map:mapList){
            Long ID = (Long)map.get("roomID");
            Long count = (Long)map.get("count");
            // 如果存在少于六人，则根据寝室内部的人数开始分配寝室

            if(count<6){

                for(;count<6;count++){
                    if(studentIter<list.size()) {
                        if(list.get(studentIter).getRoom()==null){
                            return String.format("Student %s has no room.", list.get(studentIter).getName());
                        }
                        Student student = list.get(studentIter);
                        adjustDormitories.add(
                                new AdjustDormitory()
                                        .setState("已完成")
                                        .setStudent(student.getId())
                                        .setInRoom(ID)
                                        .setOutRoom(list.get(studentIter).getRoom())
                                        .setLeader(leaderID)
                                        .setCreatedTime(LocalDateTime.now())
                                        .setModifiedTime(LocalDateTime.now())
                                        .setInBuilding(buildingID)

                        );
                        list.get(studentIter++)
                                .setRoom(ID)
                                .setModifiedTime(LocalDateTime.now());
                    }
                }
            }
        }

        if(studentIter>list.size())return "Allocate success in this building, but the building is full. You need to reassign some students' rooms.";
        this.updateBatchById(list);
        adjustDormitoryService.saveBatch(adjustDormitories);
        return "Allocate success";
    }
    public List<Indiscipline> getIndisciplineTable(Dot dot){
        return studentMapper.getIndisciplineTable(dot);
    }
    @Override
    public boolean subRepair(Long studentID, String reason){
        QueryWrapper<Student> wrapper1 = new QueryWrapper<>();
        wrapper1.eq("id",studentID);
        Long roomID = studentMapper.selectOne(wrapper1).getRoom();
        Long buildingID = roomMapper.selectById(roomID).getBuilding();
        Long dormitoryAdminID = dormitoryAdminMapper.selectOne(new QueryWrapper<DormitoryAdmin>().eq("building",buildingID)).getId();
        Repair repair = new Repair();
        repair.setState("分配中")
                .setReason(reason)
                .setStudent(studentID)
                .setDormitoryAdmin(dormitoryAdminID)
                .setCreatedTime(LocalDateTime.now())
                .setModifiedTime(LocalDateTime.now())
                .setIsDeleted(0);
        return repairMapper.insert(repair)>0;
    }
    @Override
    public List<RepairForm> getRepairTable(Dot dot){
        return repairMapper.getRepairTable(dot);
    }
}
